package org.ncibi.cytoscape.metscape.multidisplay.gui;

import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.util.Hashtable;
import java.util.List;

import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSlider;

import org.ncibi.cytoscape.metscape.multidisplay.gui.model.ControlInterface;

public class MultiNetSlider extends JPanel {

	private static final long serialVersionUID = 1L;
	
	private static final int minValue = 0;
	private static final int maxValue = 1000;
	
	private final ControlInterface control;
	
	private int minScore = 1;
	private int maxScore = 5;
	
	private double scoreToValueRatio = 4.0/1000.0;

	private List<String> labels = null;
	
	private JSlider slider = null;

	public void setScoreLabels(List<String> l){
		if (l.size() < 2) return; // must have at least two labels
		labels = l;
		setScoreRange(0,l.size()-1);
	}
	
	private void setScoreRange(int min, int max){
		if (min == max) max = min + 1;
		if (min > max) {
			int tmp = min;
			min = max;
			max = tmp;
		}
		minScore = min;
		maxScore = max;
		updateRatio();
		updateSliderTicks();
	}
	
	private double scoreFromValueDouble(int v){
		return scoreToValueRatio * (double)(v - minValue) + (double)(minScore);
	}
	
	private double valueFromScoreDouble(int s){
		return (1.0/scoreToValueRatio) * (double)(s-minScore) + (double)(minValue);
	}
	
	public void jumpToProportionalPosition(double proportionalPosition) {
		if (proportionalPosition > 1.0) proportionalPosition=1.0;
		if (proportionalPosition < 0.0) proportionalPosition=0.0;
		int sliderPosition = slider.getMinimum()
			+ (int)(proportionalPosition * (slider.getMaximum()-slider.getMinimum()));
		slider.setValue(sliderPosition);
	}
	
	private int valueFromScoreInt(int s){
		double vd = valueFromScoreDouble(s);
		int ret = (int)Math.round(vd);
		if (ret > maxValue) ret = maxValue;
		if (ret < minValue) ret = minValue;
		return ret;
	}
	
	private void updateRatio(){
		// range of scores over range of values
		scoreToValueRatio = (double)(maxScore-minScore)/(double)(maxValue-minValue);
	}
	
	private void updateSliderTicks(){
		//Create a new label table
		Hashtable<Integer,JLabel> labelTable = new Hashtable<Integer,JLabel>();
		for (int s = minScore; s <= maxScore; s++){
			String label = "" + s;
			if (labels != null){
				label = labels.get(s);
			}
			int pos = valueFromScoreInt(s);
			labelTable.put( new Integer( pos ), new JLabel(label) );
		}
		getSlider().setLabelTable( labelTable );
		getSlider().setMajorTickSpacing(valueFromScoreInt(minScore+1)-valueFromScoreInt(minScore));
		getSlider().repaint();
	}
		
	public void setScorePosition(int scorePos) {
		getSlider().setValue(valueFromScoreInt(scorePos));
	}
	
	// below this line --- generated by the visual editor
	
	/**
	 * This is the default constructor
	 */
	public MultiNetSlider(ControlInterface control) {
		super();
		this.control = control;
		initialize();
	}

	/**
	 * This method initializes this
	 * 
	 * @return void
	 */
	private void initialize() {
		GridBagConstraints gridBagConstraints = new GridBagConstraints();
		gridBagConstraints.fill = GridBagConstraints.VERTICAL;
		gridBagConstraints.gridy = 0;
		gridBagConstraints.weightx = 1.0;
		gridBagConstraints.gridx = 0;
		this.setLayout(new GridBagLayout());
		this.add(getSlider(), gridBagConstraints);
	}

	/**
	 * This method initializes slider	
	 * 	
	 * @return javax.swing.JSlider	
	 */
	private JSlider getSlider() {
		if (slider == null) {
			slider = new JSlider();
			slider.setMinimum(minValue);
			slider.setMaximum(maxValue);
			updateSliderTicks();
			slider.setPaintTicks(true);
			slider.setPaintLabels(true);
			slider.addChangeListener(new javax.swing.event.ChangeListener() {
				public void stateChanged(javax.swing.event.ChangeEvent e) {
					JSlider source = (JSlider)e.getSource();
					boolean moving = source.getValueIsAdjusting();
					double dScore = scoreFromValueDouble(getSlider().getValue());
					double dValue = (double)(getSlider().getValue());
					control.changeAnimationPosition(moving,dScore,dValue);
				}
			});
		}
		return slider;
	}

}
